package com.lheia.downloader


import com.lheia.downloader.phantomjs.WebDriverPool
import com.lheia.util.RequestExtraConstants
import org.apache.http.util.EntityUtils
import org.apache.log4j.Logger;
import org.openqa.selenium.By
import org.openqa.selenium.Cookie
import org.openqa.selenium.WebDriver
import org.openqa.selenium.WebElement;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.downloader.HttpClientDownloader
import us.codecraft.webmagic.proxy.Proxy
import us.codecraft.webmagic.proxy.ProxyProvider;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.PlainText;


/**
 * The http downloader based on HttpClient.
 *
 * @author code4crafter@gmail.com <br>
 * @since 0.1.0
 */
public class MiddlewareDownloader extends HttpClientDownloader implements Closeable {
    private volatile WebDriverPool webDriverPool
    private ProxyProvider proxyProvider;
    private Logger logger = Logger.getLogger(getClass());

    private int sleepTime = 0;

    private int poolSize = 1;
    /**
     * 失败重复无数次（每次都会自动换IP）
     * @param request
     */
    @Override
    protected void onError(Request request) {
        Object cycleTriedTimesObject = request.getExtra(Request.CYCLE_TRIED_TIMES);
        if (cycleTriedTimesObject != null) {
            request .putExtra(Request.CYCLE_TRIED_TIMES, 0);
        }
    }

    @Override
    Page download(Request request, Task task) {
        Page page = Page.fail();
        try {
            if(request.getExtra(RequestExtraConstants.PHANTOM_JS)){
                page =  downloadHeadless(request,task)
            }else{
                page =  super.download(request, task)
            }
            return page
        }catch(Exception e){
            logger.warn("download page  "+request.getUrl()+" error " , e);
            onError(request);
            return page;
        }

    }

    private Page downloadHeadless(Request request, Task task){
        checkInit();
        WebDriver webDriver;
        Proxy proxy = proxyProvider != null ? proxyProvider.getProxy(task) : null;

        try {
            webDriver = webDriverPool.get(proxy,RequestExtraConstants.PHANTOM_JS);
        } catch (InterruptedException e) {
            logger.warn("interrupted", e);
            return null;
        }
        logger.info("downloading page " + request.getUrl());
        webDriver.get(request.getUrl());
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try{
            WebDriver.Options manage = webDriver.manage();
            Site site = task.getSite();
            if (site.getCookies() != null) {
                for (Map.Entry<String, String> cookieEntry : site.getCookies()
                        .entrySet()) {
                    Cookie cookie = new Cookie(cookieEntry.getKey(),
                            cookieEntry.getValue());
                    manage.addCookie(cookie);
                }
            }

            /*
             * TODO You can add mouse event or other processes
             *
             * @author: bob.li.0718@gmail.com
             */

            WebElement webElement = webDriver.findElement(By.xpath("/html"))
            String content = webElement.getAttribute("outerHTML")
            Page page = new Page()
            page.setRawText(content)
            page.setHtml(new Html(content, request.getUrl()))
            page.setUrl(new PlainText(request.getUrl()))
            page.setRequest(request)
            webDriverPool.returnToPool(webDriver)
            return page;
        }

        finally {
            if (proxyProvider != null && proxy != null) {
                logger.info("-----!!!!!!!返还代理"+proxy)
                proxyProvider.returnProxy(proxy, page, task);
            }
        }
    }

    @Override
    void setProxyProvider(ProxyProvider proxyProvider) {
        this.proxyProvider  = proxyProvider
        super.setProxyProvider(proxyProvider)
    }

    private void checkInit() {
        if (webDriverPool == null) {
            synchronized (this) {
                webDriverPool = new WebDriverPool(poolSize);
            }
        }
    }

    MiddlewareDownloader setSleepTime(int sleepTime) {
        this.sleepTime = sleepTime;
        return this;
    }

    @Override
    void close() throws IOException {
        if(webDriverPool!=null){
            webDriverPool.closeAll();
        }
    }
}
